Imports System.Windows.Forms
Imports System.Drawing

Public Class Button3D
    Inherits Control
    Private TLC As Bitmap = My.Resources._01
    Private TRC As Bitmap = My.Resources._02
    Private BLC As Bitmap = My.Resources._03
    Private BRC As Bitmap = My.Resources._04
    Private ColMat As Single()() = {New Single() {100, 0, 0, 0, 0}, New Single() {0, 100, 0, 0, 0}, New Single() {0, 0, 100, 0, 0}, New Single() {0, 0, 0, 100, 0}, New Single() {0, 0, 0, 0, 100}}
    Private BasePic As Bitmap
    Private OutPic As Bitmap
    Private NormalPic As Bitmap
    Private DownPic As Bitmap
    Private LongPic As Bitmap
    Private Hi As Boolean = False
    Private down As Boolean = False
    Private Hicol As Color = Me.ForeColor
    Private TCol As Color = Color.Black
    Private LCol As Color = Color.Red
    Private M_Op As Integer = 100
    Private TOX As Integer = 0
    Private TOY As Integer = 0
    Private M_ButtonImage As Bitmap
    Private M_ButtonImageMode As ButtonImageModeConst = ButtonImageModeConst.None
    Private M_ResizeCustom As Integer = 75
    Private M_BIOffX As Integer
    Private M_BIOffY As Integer
    Private M_LongClick As Boolean = False
    Private M_LClick As Boolean = False
    Private M_LCTimer As Long
    Private LCDel As Integer = 1500

    Private WithEvents LTim As New System.Timers.Timer

    Delegate Sub RefreshMeCallback()

    Public Enum ButtonImageModeConst
        None = 0
        Center = 1
        Resize = 2
    End Enum

    Private Sub Button3D_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        M_LongClick = False
    End Sub
    Private Sub Button3D_ForeColorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ForeColorChanged
        UpdateButton()
    End Sub

    Private Sub Button3D_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        LTim.Interval = LCDel
        LTim.Enabled = True
        M_LClick = False
        M_LongClick = False
        down = True
        Me.Refresh()
    End Sub

    Private Sub Button3D_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
        Hi = True
        Me.Refresh()

    End Sub

    Private Sub Button3D_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
        Hi = False
        Me.Refresh()
    End Sub

    Private Sub Button3D_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        down = False
        Me.Refresh()
    End Sub
    Private Sub button2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        Dim G As Graphics = e.Graphics
        Dim W As Integer
        Dim H As Integer
        W = OutPic.Width
        H = OutPic.Height
        If Hi = True Then
            If down = True Then
                If M_LongClick = False Then
                    G.DrawImage(DownPic, 0, 0, W, H)
                Else
                    G.DrawImage(LongPic, 0, 0, W, H)
                End If
            Else
                G.DrawImage(OutPic, 0, 0, W, H)
            End If
        Else
            NormalPic.MakeTransparent(NormalPic.GetPixel(0, 0))
            G.DrawImage(NormalPic, 0, 0, W, H)
        End If
        Dim X As Integer
        Dim Y As Integer
        X = (Me.Width - G.MeasureString(Me.Text, Me.Font).Width) / 2
        Y = (Me.Height - G.MeasureString(Me.Text, Me.Font).Height) / 2
        Dim BR As New SolidBrush(TCol)
        If Me.Text > "" Then
            If down = False Then
                G.DrawString(Me.Text, Me.Font, BR, X - 1 + TOX, Y - 1 + TOY)
            Else
                G.DrawString(Me.Text, Me.Font, BR, X + 1 + TOX, Y + 1 + TOY)
            End If
        End If
        If M_ButtonImage IsNot Nothing Then
            If M_ButtonImageMode = ButtonImageModeConst.None Then
                G.DrawImage(M_ButtonImage, 0, 0)
            End If
            If M_ButtonImageMode = ButtonImageModeConst.Center Then
                Dim BIX As Integer
                Dim BIY As Integer
                If down = False Then
                    BIX = ((Me.Width / 2) - (M_ButtonImage.Width / 2) - 1) + M_BIOffX
                    BIY = ((Me.Height / 2) - (M_ButtonImage.Height / 2) - 1) + M_BIOffY
                Else
                    BIX = ((Me.Width / 2) - (M_ButtonImage.Width / 2) + 1) + M_BIOffX
                    BIY = ((Me.Height / 2) - (M_ButtonImage.Height / 2) + 1) + M_BIOffY
                End If
                G.DrawImage(M_ButtonImage, BIX, BIY)
            End If
            If M_ButtonImageMode = ButtonImageModeConst.Resize Then
                Dim BIX As Integer
                Dim BIY As Integer
                Dim BIW As Integer = (Me.Width * (M_ResizeCustom / 100)) - 4
                Dim BIH As Integer = (Me.Height * (M_ResizeCustom / 100)) - 4
                If down = False Then
                    BIX = (Me.Width / 2) - (BIW / 2) - 1 + M_BIOffX
                    BIY = (Me.Height / 2) - (BIH / 2) - 1 + M_BIOffY
                Else
                    BIX = (Me.Width / 2) - (BIW / 2) + 1 + M_BIOffX
                    BIY = (Me.Height / 2) - (BIH / 2) + 1 + M_BIOffY
                End If
                G.DrawImage(M_ButtonImage, BIX, BIY, BIW, BIH)
            End If

        End If
        BR.Dispose()
    End Sub
    Private Sub DrawBase()
        If Me.Height < 1 Then Me.Height = 10
        If Me.Width < 1 Then Me.Width = 10

        Dim BP As New Bitmap(Me.Width, Me.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        TLC.MakeTransparent(Color.White)
        TRC.MakeTransparent(Color.White)
        BLC.MakeTransparent(Color.White)
        BRC.MakeTransparent(Color.White)
        Dim g As Graphics = Graphics.FromImage(BP)
        Dim X As Integer
        Dim Y As Integer
        Dim W As Integer = TLC.Width / 3
        Dim H As Integer = TLC.Height / 3
        Dim r As New Rectangle(W / 2, H / 2, Me.Width - W, Me.Height - H)
        Dim Col As Color = BRC.GetPixel(0, 0)
        Dim BR As New SolidBrush(Col)
        g.Clear(Color.Transparent)
        g.FillRectangle(BR, r)
        For X = W To (BP.Width - W)
            g.DrawImage(TRC, X, 0, W, H)
            g.DrawImage(BRC, X, BP.Height - H, W, H)
        Next X
        For Y = H To (BP.Height - H)
            g.DrawImage(BLC, 0, Y, W, H)
            g.DrawImage(BRC, BP.Width - W, Y, W, H)
        Next
        g.DrawImage(BLC, 0, BP.Height - H, W, H)
        g.DrawImage(TLC, 0, 0, W, H)
        BR.Dispose()
        BasePic = New Bitmap(BP)
        BP.Dispose()
    End Sub
    Private Sub Colorize(ByVal Col As Color)
        OutPic = New Bitmap(BasePic.Width, BasePic.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        Dim R As Double
        Dim G As Double
        Dim B As Double
        Dim S As Double = 100 / 255
        Dim Op As Double
        R = (Col.R * S) / 100
        G = (Col.G * S) / 100
        B = (Col.B * S) / 100
        Op = M_Op / 100
        Dim Mat As Single()() = { _
                New Single() {R, 0, 0, 0, 0}, _
                New Single() {0, G, 0, 0, 0}, _
                New Single() {0, 0, B, 0, 0}, _
                New Single() {0, 0, 0, Op, 0}, _
                New Single() {0, 0, 0, 0, 1}}

        Dim colorMatrix As New System.Drawing.Imaging.ColorMatrix(Mat)

        ' Create an ImageAttributes object and set its color matrix.
        Dim imageAtt As New System.Drawing.Imaging.ImageAttributes()
        imageAtt.SetColorMatrix(colorMatrix, System.Drawing.Imaging.ColorMatrixFlag.Default, System.Drawing.Imaging.ColorAdjustType.Bitmap)
        imageAtt.SetColorKey(System.Drawing.Color.Black, System.Drawing.Color.White)

        Dim r1 As RectangleF
        r1.X = 0
        r1.Y = 0
        r1.Width = OutPic.Width
        r1.Height = OutPic.Height

        Dim r2 As RectangleF
        r2.X = 0
        r2.Y = 0
        r2.Width = OutPic.Width
        r2.Height = OutPic.Height


        Dim Grap As Graphics = Graphics.FromImage(OutPic)
        Dim brush3 As New TextureBrush(BasePic, r1, imageAtt)
        Grap.FillRectangle(brush3, r2)
        Grap.Dispose()
        brush3.Dispose()

    End Sub
    Private Sub Flip()
        DownPic = New Bitmap(OutPic)
        DownPic.RotateFlip(RotateFlipType.Rotate180FlipNone)

    End Sub
    Private Sub Button3D_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        DrawBase()

        Colorize(LCol)
        LongPic = New Bitmap(OutPic)
        LongPic.RotateFlip(RotateFlipType.Rotate180FlipNone)

        Colorize(Me.ForeColor)
        NormalPic = New Bitmap(OutPic)
        Colorize(Hicol)
        Flip()


    End Sub
    Public Property HiLiteColor() As Color
        Get
            Return Hicol
        End Get
        Set(ByVal value As Color)
            Hicol = value
            UpdateButton()
        End Set
    End Property
    Public Property TextColor() As Color
        Get
            Return TCol
        End Get
        Set(ByVal value As Color)
            TCol = value
            Me.Refresh()

        End Set
    End Property

    Public Sub New()
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        Me.BackColor = Color.Transparent
    End Sub
    Public Property Opacity() As Integer
        Get
            Return M_Op
        End Get
        Set(ByVal value As Integer)
            M_Op = value
            Me.Refresh()
        End Set
    End Property
    Public Property TextOffsetX() As Integer
        Get
            Return TOX
        End Get
        Set(ByVal value As Integer)
            TOX = value
            Me.Refresh()
        End Set
    End Property
    Public Property TextOffsetY() As Integer
        Get
            Return TOY
        End Get
        Set(ByVal value As Integer)
            TOY = value
            Me.Refresh()
        End Set
    End Property
    Public Property ButtonImage() As Bitmap
        Get
            Return M_ButtonImage
        End Get
        Set(ByVal value As Bitmap)
            M_ButtonImage = value
            Me.Refresh()
        End Set
    End Property
    Public Property ButtonImageMode() As ButtonImageModeConst
        Get
            Return M_ButtonImageMode
        End Get
        Set(ByVal value As ButtonImageModeConst)
            M_ButtonImageMode = value
            Me.Refresh()
        End Set
    End Property
    Public Property ButtonImageCustomResize() As Integer
        Get
            Return M_ResizeCustom
        End Get
        Set(ByVal value As Integer)
            If value > 0 And value < 101 Then
                M_ResizeCustom = value
                Me.Refresh()
            End If

        End Set
    End Property
    Public Property ButtonImageOffsetX() As Integer
        Get
            Return M_BIOffX
        End Get
        Set(ByVal value As Integer)
            M_BIOffX = value
            Me.Refresh()
        End Set
    End Property
    Public Property ButtonImageOffsetY() As Integer
        Get
            Return M_BIOffY
        End Get
        Set(ByVal value As Integer)
            M_BIOffY = value
            Me.Refresh()
        End Set
    End Property
    Public Sub UpdateButton()
        DrawBase()

        Colorize(LCol)
        LongPic = New Bitmap(OutPic)
        LongPic.RotateFlip(RotateFlipType.Rotate180FlipNone)

        Colorize(Me.ForeColor)
        NormalPic = New Bitmap(OutPic)
        Colorize(Hicol)
        Flip()


    End Sub

    Private Sub LTim_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles LTim.Elapsed
        LTim.Enabled = False
        M_LongClick = True
        M_LClick = True
        RefreshMe()
    End Sub
    Private Sub RefreshMe()
        If Me.InvokeRequired Then
            Dim d As New RefreshMeCallback(AddressOf RefreshMe)
            Me.Invoke(d)
        Else
            Me.Refresh()
        End If

    End Sub
    Public ReadOnly Property Longclick() As Boolean
        Get
            Return M_LClick
        End Get
    End Property
    Public Property LongClickColor() As Color
        Get
            Return LCol
        End Get
        Set(ByVal value As Color)
            LCol = value
            UpdateButton()
        End Set
    End Property
    Public Property LongClickDelay() As Integer
        Get
            Return LCDel
        End Get
        Set(ByVal value As Integer)
            LCDel = value
        End Set
    End Property
End Class
